/**
 * @file
 * @author  Tsin Smith <tsin.creator@gmail.com>
 *
 */

#ifndef __TSIN_UTIL_ARRAYSET_HPP__
#define __TSIN_UTIL_ARRAYSET_HPP__

#include <tsin/util/Set.hpp>

#include <cstring>

namespace tsin {

        /**
         * @class ArraySet
         * @ingroup util
         * @brief A runtime pointer container implemented using an array.
         */
        template <class T>
        class ArraySet : public Set<T>
        {
        public:
                ArraySet(int capacity = 1500)
                        : nextSlot(0), usedSlots(0), iterator(0)
                {
                        this->capacity = capacity;
                        array = new T[this->capacity];
                        memset(array, 0, this->capacity * sizeof(void*));
                }

                virtual ~ArraySet()
                {
                        delete[] array;
                }

                virtual int size()
                {
                        return usedSlots;
                }

                virtual bool insert(T ptr)
                {
                        if (ptr == 0)
                                return false;
                        if (usedSlots >= capacity)
                                return false;

                        array[nextSlot ++] = ptr;
                        usedSlots ++;
                        if(usedSlots < capacity)
                                while (array[nextSlot] != 0) {
                                        nextSlot ++;
                                        if(nextSlot >= capacity)
                                                nextSlot = 0;
                                }
                        return true;
                }

                virtual T remove()
                {
                        T ptr = array[iterator];
                        array[iterator] = 0;
                        if (usedSlots >= capacity)
                                nextSlot = iterator;
                        usedSlots --;
                        return ptr;
                }

                virtual bool atBegin()
                {
                        return (iterator <= 0);
                }

                virtual bool atEnd()
                {
                        return (iterator >= capacity);
                }

                virtual void toBegin()
                {
                        iterator = -1;
                        next();
                }

                virtual void toEnd()
                {
                        iterator = capacity;
                }

                virtual void prev()
                {
                        if (iterator < 0)
                                return;

                        do {
                                iterator --;
                        } while (iterator >= 0 && array[iterator] == 0);
                }

                virtual void next()
                {
                        if (iterator >= capacity)
                                return;

                        do {
                                iterator ++;
                        } while (iterator < capacity && array[iterator] == 0);
                }

                virtual T get()
                {
                        if (iterator >= 0 && iterator < capacity)
                                return array[iterator];
                        return 0;
                }

        private:
                T *array;
                int capacity;

                int usedSlots;
                int nextSlot;

                int iterator;
        };

}

#endif /* __TSIN_UTIL_ARRAYSET_HPP__ */
